package net.qiqbframework.mf;

import com.mybatisflex.core.BaseMapper;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateWrapper;
import com.mybatisflex.core.util.ClassUtil;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import net.qiqbframework.common.utils.CollectionUtil;
import net.qiqbframework.common.utils.StringUtil;
import net.qiqbframework.persisthanding.dao.BasicEntityPo;
import net.qiqbframework.persisthanding.dao.BasicEntityPoDao;

import java.util.*;

@Slf4j
public class BasicEntityPoDaoMfImpl<M extends BaseMapper<Po>, Po extends BasicEntityPo> extends
        ServiceImpl<M, Po> implements BasicEntityPoDao<Po> {


    private String DEFAULT_ENTITY_ID = "id";

    public void setIdPropertyName(String idPropertyName) {
        this.DEFAULT_ENTITY_ID = idPropertyName;
    }


    public BasicEntityPoDaoMfImpl() {
        // 扫描ID


    }

    @Override
    public List<Po> batchSelectPosByIds(Collection<String> ids) {
        if (CollectionUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return super.listByIds(ids);
    }

    @Override
    public Po selectPoById(String id) {
        if (StringUtil.isEmpty(id)) {
            return null;
        }
        return super.getById(id);
    }

    @Override
    public boolean dynamicUpdateById(Po newPO, Po oldPO) {
        final Map<String, Object> changedFields = comparePo(newPO, oldPO);
        if (changedFields.isEmpty()) {
            log.info("没有变更字段，无需更新，新值:{},旧值:{}", newPO, oldPO);
            return false;
        }
        Class usefulClass = ClassUtil.getUsefulClass(newPO.getClass());
        UpdateWrapper<Po> updateWrapper = UpdateWrapper.of(usefulClass);
        for (Map.Entry<String, Object> changedField : changedFields.entrySet()) {
            updateWrapper.set(changedField.getKey(), changedField.getValue());
        }
        QueryWrapper queryWrapper = QueryWrapper.create().eq(DEFAULT_ENTITY_ID, newPO.getId());
        super.update(updateWrapper.toEntity(), queryWrapper);
        return true;
    }


    @Override
    public boolean batchDynamicUpdateById(Map<Po, Po> newAndOldMap) {
        List<Po> preUpdate = new ArrayList<>();
        Map<Po, Map<String, Object>> changedFieldsGroup = new HashMap<>();
        for (Map.Entry<Po, Po> entry : newAndOldMap.entrySet()) {
            final Po newPO = entry.getKey();
            final Po oldPO = entry.getValue();
            final Map<String, Object> changedFields = comparePo(newPO, oldPO);
            if (changedFields.isEmpty()) {
                log.info("批量没有变更字段，无需更新，新值:{},旧值:{}", newPO, oldPO);
                continue;
            }
            changedFieldsGroup.put(newPO, changedFields);
        }
        if (changedFieldsGroup.isEmpty()) {
            log.info("集合中未找到变更的对象");
            return false;
        }
        Class usefulClass = null;
        Set<String> updatedPoIds = new HashSet<>();
        // 比较变化的值。如果值一直，统一更新，否则一条条更新
        for (Map.Entry<Po, Po> entry : newAndOldMap.entrySet()) {
            if (updatedPoIds.contains(entry.getKey().getId())) {
                continue;
            }
            if (changedFieldsGroup.containsKey(entry.getKey())) {
                List<String> sameUpdatePoIds = new ArrayList<>();
                Map<String, Object> changedFields = changedFieldsGroup.get(entry.getKey());
                for (Map.Entry<Po, Map<String, Object>> changeMap : changedFieldsGroup.entrySet()) {
                    if (changeMap.getValue().equals(changedFields)) {
                        sameUpdatePoIds.add(changeMap.getKey().getId());
                    }
                }
                if (usefulClass == null) {
                    usefulClass = ClassUtil.getUsefulClass(entry.getValue().getClass());
                }
                UpdateWrapper<Po> updateWrapper = UpdateWrapper.of(usefulClass);
                for (Map.Entry<String, Object> changedField : changedFields.entrySet()) {
                    updateWrapper.set(changedField.getKey(), changedField.getValue());
                }
                QueryWrapper queryWrapper = QueryWrapper.create();
                if (sameUpdatePoIds.size() > 1) {
                    queryWrapper.in(DEFAULT_ENTITY_ID, sameUpdatePoIds);
                } else {
                    queryWrapper.eq(DEFAULT_ENTITY_ID, sameUpdatePoIds.get(0));
                }
                updatedPoIds.addAll(sameUpdatePoIds);
                super.update(updateWrapper.toEntity(), queryWrapper);
            }
        }
        return super.updateBatch(preUpdate);
    }


    @Override
    public boolean batchInsertPos(Collection<Po> pos) {
        if (CollectionUtil.isEmpty(pos)) {
            return false;
        }
        return super.saveBatch(pos);
    }

    @Override
    public boolean batchDeletePosById(Collection<Po> pos) {
        if (CollectionUtil.isEmpty(pos)) {
            return false;
        }

        return super.removeByIds(pos.stream().map(BasicEntityPo::getId).toList());
    }


}
